package com.hand.wfive.loginAndVip;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;

public class MD5Util {

    private static final char[] DIGITS_LOWER = "0123456789abcdef".toCharArray();
    private static final char[] DIGITS_UPPER = "0123456789ABCDEF".toCharArray();

    public static String getPasswordMd5(String input) {
        return encode("MD5", input, true);
    }

    /**
     * 生成签名信息
     *
     * @param secretKey 产品私钥
     * @param params    接口请求参数名和参数值map，不包括signature参数名
     */
    public static String genSignature(String secretKey, Map<String, String> params) {
        // 1. 参数名按照ASCII码表升序排序
        String[] keys = params.keySet().toArray(new String[0]);
        Arrays.sort(keys);

        // 2. 按照排序拼接参数名与参数值
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            sb.append(key).append(params.get(key));
        }
        // 3. 将secretKey拼接到最后
        sb.append(secretKey);

        // 4. MD5是128位长度的摘要算法，转换为十六进制之后长度为32字符
        return md5Hex(sb.toString());
    }

    private static String md5Hex(String data) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            byte[] bytes = messageDigest.digest(data.getBytes(StandardCharsets.UTF_8));
            final int l = bytes.length;
            final char[] out = new char[l << 1];
            for (int i = 0, j = 0; i < bytes.length; i++) {
                out[j++] = DIGITS_LOWER[(0xF0 & bytes[i]) >>> 4];
                out[j++] = DIGITS_LOWER[0x0F & bytes[i]];
            }
            return new String(out);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 验证码登录
     * 计算并获取CheckSum
     */
    public static String getCheckSum(String appSecret, String nonce, String curTime) {
        return encode("sha1", appSecret + nonce + curTime, false);
    }

    private static String encode(String algorithm, String value, boolean isUpper) {
        if (value == null) {
            return null;
        }
        try {
            MessageDigest messageDigest
                    = MessageDigest.getInstance(algorithm);
            messageDigest.update(value.getBytes());
            return getFormattedText(messageDigest.digest(), isUpper);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getFormattedText(byte[] bytes, boolean isUpper) {
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        for (byte aByte : bytes) {
            buf.append(isUpper? DIGITS_UPPER[(aByte >> 4) & 0x0f]: DIGITS_LOWER[(aByte >> 4) & 0x0f]);
            buf.append(isUpper? DIGITS_UPPER[aByte & 0x0f]: DIGITS_LOWER[aByte & 0x0f]);
        }
        return buf.toString();
    }
}
